/**
 * 
 */
package com.netscenery.yang.model;

import java.util.ArrayList;

import org.jdom2.Attribute;
import org.jdom2.Element;

import com.netscenery.util.ErrTag;
import com.netscenery.util.QName;
import com.netscenery.util.XMLTag;
import com.netscenery.yang.YangKeyword;
import com.netscenery.yang.YangStatement;
import com.netscenery.yang.designer.MapInfo;
import com.netscenery.yang.parser.YangParserException;


/**
 * @author yanzi
 *
 */
public class Identity extends Entity {

	private String base;

	/**
	 * 
	 */
	public Identity() {
		// TODO Auto-generated constructor stub
	}

	/**
	 * @param env
	 * @param name
	 * @throws ModelException 
	 */
	public Identity(Env env, String name) throws ModelException {
		super(env, name);
		// TODO Auto-generated constructor stub
	}

	/**
	 * @param env
	 * @param qname
	 */
	public Identity(Env env, QName qname) {
		super(env, qname);
		// TODO Auto-generated constructor stub
	}


	/**
	 * @return the base
	 */
	public String getBase() {
		return base;
	}

	/**
	 * @param base the base to set
	 */
	public void setBase(String base) {
		this.base = base;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#toYang()
	 */
	@Override
	public YangStatement toYang() {
		YangStatement statement = new YangStatement(YangKeyword.IDENTITY.getKeyword(),this.name);

		if (!isNullString(this.description)){
			YangStatement descr = new YangStatement(YangKeyword.DESCRIPTION.getKeyword(),this.description);
			statement.addChild(descr);
		}
		if (null != this.reference){
			YangStatement ref = new YangStatement(YangStatement.YANG_STATEMENT_REFERENCE,this.getReference());
			statement.addChild(ref);
		}
		
		if (Status.CURRENT != this.status){
			YangStatement status = new YangStatement(YangStatement.YANG_STATEMENT_STATUS,this.getStatus().getStatus());
			statement.addChild(status);
		}
		if (null != base){
			YangStatement baseStatement = new YangStatement(YangKeyword.BASE.getKeyword(),base);
			
			statement.addChild(baseStatement);	
		}
		
		
		return statement;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#toYin()
	 */
	@Override
	public Element toYin() {
		Element element = new Element(YangKeyword.IDENTITY.getKeyword(),env.getNs());
		Attribute name = new Attribute("name",this.name);
		element.setAttribute(name);
		
	
		if (!isNullString(this.getDescription())){
			Element descr = new Element(YangStatement.YANG_STATEMENT_DESCRIPTION,env.getNs());
			Element text = new Element(XMLTag.XML_TAG_TEXT,env.getNs());
			text.setText(this.getDescription());
			descr.addContent(text);
			element.addContent(descr);
		}
		if (null != this.getReference()){
			Element ref = new Element(YangStatement.YANG_STATEMENT_REFERENCE,env.getNs());
			Element text = new Element(XMLTag.XML_TAG_TEXT,env.getNs());
			text.setText(this.getReference());
			ref.addContent(text);
			element.addContent(ref);
		}
		
		if (Status.CURRENT != this.getStatus()){
			Element status = new Element(YangStatement.YANG_STATEMENT_STATUS,env.getNs());
			Attribute value = new Attribute(YangKeyword.VALUE.getKeyword(),this.getStatus().getStatus());
			status.setAttribute(value);
			element.addContent(status);
		}
		if (null != base){
			Element baseElement = new Element(YangKeyword.BASE.getKeyword(),env.getNs());
			Attribute basename = new Attribute("name",base);
			baseElement.setAttribute(basename);			
			element.addContent(baseElement);			
		}
		return element;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#toXML()
	 */
	@Override
	public Element toXML() {
		// TODO Auto-generated method stub
		return null;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#readXML(org.jdom2.Element)
	 */
	@Override
	public int readXML(Element element) throws ModelException {
		// TODO Auto-generated method stub
		return 0;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#readYin(org.jdom2.Element)
	 */
	@Override
	public int readYin(Element element) throws ModelException {
		if (null == element){
			return MODELELEMENT_OK;
		}

		// ����
		if (element.getName()
				.equals(YangStatement.YANG_STATEMENT_DESCRIPTION)) {
			Element text = element.getChild(XMLTag.XML_TAG_TEXT, env.getNs());
			if (null == text) {
				return MODELELEMENT_FAIL;
			}
			this.setDescription(text.getText());
		}
		
		// reference
		else if (element.getName().equals(
				YangStatement.YANG_STATEMENT_REFERENCE)) {

			Element text = element.getChild(XMLTag.XML_TAG_TEXT, env.getNs());
			if (null == text) {
				return MODELELEMENT_FAIL;
			}
			this.setReference(text.getText());
		}
		// status
		else if (element.getName()
				.equals(YangStatement.YANG_STATEMENT_STATUS)) {
			String value = element.getAttributeValue(YangKeyword.VALUE
					.getKeyword());
			if (null == value) {
				return MODELELEMENT_FAIL;
			} else {
				this.status = Status.getStatus(value);
			}

		}
		
		// base
		else if (element.getName().equals(
				YangKeyword.BASE)) {
			String value= element.getAttributeValue(XMLTag.XML_TAG_NAME);
			if (null == value){
				return MODELELEMENT_FAIL;
			}
			this.setBase(value);
		}
		
		return MODELELEMENT_OK;	
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#readYANG(com.netscenery.yang.YangStatement)
	 */
	@Override
	public int readYANG(YangStatement statement) throws YangParserException {
		if (null == statement){
			return MODELELEMENT_OK;
		}
		String value = statement.getArgument();
		
		//����
		if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_DESCRIPTION)){
			this.setDescription(value);
		}

	    //reference
		else if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_REFERENCE)){
			this.setReference(value);
		}
	    //status
		else if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_STATUS)){
			this.setStatus(Status.getStatus(value));
		}
		// base
		else if (statement.getKeyword().equals(
				YangStatement.YANG_STATEMENT_BASE)) {
			this.setBase(value);
		}
		
		return MODELELEMENT_OK;
	}
	
	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#validate()
	 */
	@Override
	public Validator validate() {
		Validator validator  = new Validator();
		//base
		Module curModule = env.getCurModule();
		ArrayList<String> availableIdentities = curModule.getAvailableIdentityNames();
		if (null == availableIdentities ){
			if (null != base){
				validator.setIsValid(false);
				validator.addMsg(new Message(this,ErrTag.ERROR,"base","referenced identity is not exist."));
			}
		}
		else {
			if (null != base){
				QName baseName = new QName(base);
				String prefix = baseName.getPrefix();
				String localName = baseName.getLocalName();
				String modulePrefix = null;
				if (curModule instanceof MainModule){
					modulePrefix = ((MainModule)curModule).getPrefix();
				}
				else {
					SubModule sb = (SubModule) curModule;
					
					MainModule mm = (MainModule) env.getModule(sb.getBelongsto().getName());
					modulePrefix = mm.getPrefix();
				}
				
				String baseActualName= null;
				if (prefix.equals(modulePrefix)){
					baseActualName = localName;
				}
				else {
					baseActualName = base;
				}
				//�ж�prefix�Ƿ�Ϊ��ģ�飬���Ϊ��ģ�飬��ʹ��localName�ж��Ƿ���ڵ�ǰ
				//���õ�ʵ����				
				if (!availableIdentities.contains(baseActualName)){
					validator.setIsValid(false);
					validator.addMsg(new Message(this,ErrTag.ERROR,"base","referenced identity is not exist."));
				}
			}
		}
		
		Validator sValidator = super.validate();
		validator.copy(sValidator);
		
		
		return validator;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#isFieldMandatory(java.lang.String)
	 */
	@Override
	public boolean isFieldMandatory(String field) {
		// TODO Auto-generated method stub
		return false;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#getMapInfo()
	 */
	@Override
	public MapInfo getMapInfo() throws SecurityException, NoSuchMethodException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void update() {
		// TODO Auto-generated method stub
		
	}

}
